﻿// 
//

#include "pch.h"
#include <iostream>
#include <opencv2/opencv.hpp>
#include <vector>

using namespace cv;
using namespace std;

int main()
{
	Mat imageRice = imread("E:\\VC_project\\figure\\rice.png");

	Mat grayRice, bwRice;//二值化后图像

    //先对图像进行灰度化处理
	cvtColor(imageRice, grayRice, COLOR_BGR2GRAY);

	//大津算法进行阈值化处理
	threshold(grayRice, bwRice, 0, 255, CV_THRESH_OTSU);

	//形态学去噪
	Mat element = getStructuringElement(MORPH_CROSS, Size(3, 3));
	morphologyEx(bwRice, bwRice, MORPH_OPEN, element);

	//对图像进行分割
	Mat seq = bwRice.clone();
	vector<vector<Point>> cnts;
	findContours(seq, cnts, RETR_EXTERNAL, CHAIN_APPROX_SIMPLE);
	
	double area;//计算每个米粒的面积
	double areaArray[92];
	double lengthArray[92];//计算每个米粒的长度
	int count = 0;//统计米粒数量
	Rect rect;//计算轮廓包围的矩形
	string strCount;
	//对图像进行筛选
	for (int i = cnts.size() - 1; i > 0; i--)
	{
		vector<Point> c = cnts[i];
		area = contourArea(c);
		if (area < 10)  //滤除面积小于10的分割面积，可能是噪声
			continue;
		count++;
		areaArray[count - 1] = area;
		lengthArray[count - 1] = arcLength(c,1);
		cout << "blob " << i << " : " << area << endl;
		rect = boundingRect(c);
		//在原始图像上画出包围的矩形，并给每个矩形标号
		rectangle(imageRice, rect, Scalar(0, 0, 255), 1);

		stringstream ss;
		ss << count;
		ss >> strCount;
		putText(imageRice, strCount, Point(rect.x, rect.y), CV_FONT_HERSHEY_PLAIN, 0.5, Scalar(0, 255, 0));

	}
	cout << "米粒数量: " << count << endl;
	
	//计算米粒长度和面积的均值
	double aveLength, aveArea, varLength, varArea;
	double sumLength = 0, sumArea = 0;
	for (int i = 0; i < count; i++)
	{
		sumLength += lengthArray[i];
		sumArea += areaArray[i];
	}
	aveArea = sumArea / count;
	aveLength = sumLength / count;

	//计算长度和面积的方差
	double sumVarArea = 0, sumVarLength = 0;
	for (int i = 0; i < count; i++)
	{
		sumVarArea += (areaArray[i] - aveArea)*(areaArray[i] - aveArea);
		sumVarLength += (lengthArray[i] - aveLength)*(lengthArray[i] - aveLength);
	}
	varArea = sumVarArea / count;
	varLength = sumVarLength / count;

	cout << "米粒平均长度: " << aveLength << endl;
	cout << "米粒平均面积: " << aveArea << endl;
	cout << "米粒长度方差: " << varLength << endl;
	cout << "米粒面积方差: " << varArea << endl;

	//计算落在3 sigma的米粒的数量
	int count3sigma = 0;
	double sigmaArea = sqrt(varArea);
	for (int i = 0; i < count; i++)
	{
		if (areaArray[i] > (aveArea - 3 * sigmaArea) || areaArray[i] < (aveArea + 3 * sigmaArea))
			count3sigma++;
	}
	cout << "米粒落在3sigma的数量: " << count3sigma << endl;
	imshow("阈值化处理", bwRice);
	imshow("用矩形标记米粒", imageRice);
	waitKey();
}


